package press.xiang.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import press.xiang.entity.Commodity;
import press.xiang.entity.CommodityVO;
import press.xiang.entity.Store;
import press.xiang.service.ICommodityService;
import press.xiang.service.IStoreService;
import press.xiang.utils.TabuUtils;

import java.util.*;

/**
 * 任务调度
 * 仓库间货物调度、进仓出仓、路线解决接口
 * @author xiang
 * @version 1.0
 * @description: TODO
 * @date 2022/4/22 1:44 下午
 */
@RestController
@RequestMapping("dispatch")
@AllArgsConstructor
@Slf4j
public class DispatchController {

    private final ICommodityService commodityService;
    private final IStoreService storeService;


    /**
     * @description: 获取所有仓库中的商品信息
     * @return: 返回仓库商品信息
     * @author xiang
     * @date: 2022/4/22 4:22 下午
     */
    @GetMapping("get-commodity-info")
    public R<List<Map<String,Object>>> getCommodityInfo(){
        List<CommodityVO> data = commodityService.queryStoreByCommodity();
        List<CommodityVO> count = commodityService.queryStoreByCount();
        List<Map<String,Object>> list = new ArrayList<>();
        for (CommodityVO c : count) {
            Map<String,Object> result = new HashMap<>();
            // 仓库名
            String storeName = c.getStoreName();
            List<Map<String,Double>> commodityInfoList = new ArrayList<>();
            for (CommodityVO d : data) {
                if (d.getStoreName().equals(storeName)) {
                    Map<String,Double> commodityInfo = new HashMap<>();
                    String commodityName = d.getName();
                    Double commodityTotal = d.getTotal();
                    commodityInfo.put(commodityName, commodityTotal);
                    commodityInfoList.add(commodityInfo);
                }
            }
            result.put("仓库名",storeName);
            result.put("商品数量",c.getCommodityCount());
            result.put("商品信息",commodityInfoList);
            list.add(result);
        }
        return R.ok(list);
    }


    @GetMapping("query-commodity-store")
    public R queryCommodityStore(String name){
        List<CommodityVO> data = commodityService.queryStoreByCommodity();
        Map<String,Object> map = new HashMap<>();
        for (CommodityVO d : data) {
            if(!d.getName().equals(name)){
                continue;
            }
            map.put(d.getStoreName(),d.getTotal());
        }
        return R.ok(map);
    }


    @PostMapping("add-commodity-info")
    public R addCommodityInfo(@RequestBody Commodity commodity){
        // 新增商品
        List<Commodity> list = commodityService.list(Wrappers.<Commodity>query().lambda().eq(Commodity::getName, commodity.getName()));
        for (Commodity co : list) {
            double add = co.getTotal() + commodity.getTotal();
            co.setTotal(add);
            co.updateById();
        }
        return R.ok("success");
    }

    @PostMapping("dec-commodity-info")
    public R decCommodityInfo(@RequestBody Commodity commodity){
        // 新增商品
        List<Commodity> list = commodityService.list(Wrappers.<Commodity>query().lambda().eq(Commodity::getName, commodity.getName()));
        for (Commodity co : list) {
            double add = co.getTotal() - commodity.getTotal();
            co.setTotal(add);
            if (add<0){
                co.setTotal(0D);
            }
            co.updateById();
        }
        return R.ok("success");
    }


    @GetMapping("dispatch-path")
    public R dispatchPath(String name){
        List<Store> pathList = storeService.getStorePathByCommodityName(name);
        if (pathList.size()<=2){
            StringJoiner sj = new StringJoiner("->");
            for (Store store : pathList) {
                sj.add(store.getName());
            }
            String s = sj.toString();
            return R.ok("调度最优路径为： "+s);
        }

        double[][] data = new double[pathList.size()][pathList.size()];
        // 根据坐标生成每个点之间的距离长度
        for (int i = 0; i < pathList.size(); i++) {
            String longAndLatFirst = pathList.get(i).getLongAndLat();
            String[] splitf = longAndLatFirst.split(",");
            int lf = Integer.parseInt(splitf[0]);
            int tf = Integer.parseInt(splitf[1]);

            for (int j = 0; j < pathList.size(); j++) {
                String longAndLatSecond = pathList.get(j).getLongAndLat();
                String[] splits = longAndLatSecond.split(",");
                int ls = Integer.parseInt(splits[0]);
                int ts = Integer.parseInt(splits[1]);

                int h = (ls - lf)>0? ls-lf:((ls-lf)*-1);
                int w = (ts - tf)>0? ts-tf:((ts-tf)*-1);
                int c = h*h+w*w;
                int sqrt = (int)Math.sqrt(c);
                data[i][j] = sqrt;
            }
        }


        int tabuLength = pathList.size() / 4;
        int optNum = pathList.size() / 2;

        int[] ints = TabuUtils.optTspByTabu(data, tabuLength, optNum);
        StringJoiner sj = new StringJoiner("->");
        for (int anInt : ints) {
            String storeName = pathList.get(anInt).getName();
            sj.add(storeName);
        }
        String s = sj.toString();
        return R.ok("调度最优路径为： "+s);
    }


    @GetMapping("get-tabu")
    public R getTabu(){
        List<Store> pathList = storeService.list();
        if (pathList.size()<=2){
            StringJoiner sj = new StringJoiner("->");
            List<int[]> path = new ArrayList<>();
            for (Store store : pathList) {
                sj.add(store.getName());
                String longAndLat = store.getLongAndLat();
                String[] split = longAndLat.split(",");
                int[] s = new int[split.length];
                for (int i = 0; i < split.length; i++) {
                    s[i] = Integer.parseInt(split[i]);
                }
                path.add(s);
            }
            String s = sj.toString();

            Map<String,Object> map = new HashMap<>();
            map.put("path",s);
            map.put("data",path);



            return R.ok(map);
        }else{
            double[][] data = new double[pathList.size()][pathList.size()];
            // 根据坐标生成每个点之间的距离长度
            for (int i = 0; i < pathList.size(); i++) {
                String longAndLatFirst = pathList.get(i).getLongAndLat();
                String[] splitf = longAndLatFirst.split(",");
                int lf = Integer.parseInt(splitf[0]);
                int tf = Integer.parseInt(splitf[1]);

                for (int j = 0; j < pathList.size(); j++) {
                    String longAndLatSecond = pathList.get(j).getLongAndLat();
                    String[] splits = longAndLatSecond.split(",");
                    int ls = Integer.parseInt(splits[0]);
                    int ts = Integer.parseInt(splits[1]);

                    int h = (ls - lf)>0? ls-lf:((ls-lf)*-1);
                    int w = (ts - tf)>0? ts-tf:((ts-tf)*-1);
                    int c = h*h+w*w;
                    int sqrt = (int)Math.sqrt(c);
                    data[i][j] = sqrt;
                }
            }


            int tabuLength = pathList.size() / 4;
            int optNum = pathList.size() / 2;

            int[] ints = TabuUtils.optTspByTabu(data, tabuLength, optNum);
            StringJoiner sj = new StringJoiner("->");
            for (int anInt : ints) {
                String storeName = pathList.get(anInt).getName();
                sj.add(storeName);
            }
            String s = sj.toString();

            List<int[]> path = new ArrayList<>();
            for (Store store : pathList) {
                sj.add(store.getName());
            }

            for (int i = 0; i < ints.length; i++) {
                Store store = pathList.get(ints[i]);
                String[] split = store.getLongAndLat().split(",");
                int[] sp = new int[split.length];
                for (int j = 0; j < split.length; j++) {
                    sp[j] = Integer.parseInt(split[j]);
                }
                path.add(sp);
            }

            String sp = sj.toString();

            Map<String,Object> map = new HashMap<>();
            map.put("path",sp);
            map.put("data",path);


            return R.ok(map);
        }
    }
}
